non-modal convenience functions
You can create complete sophisticated applications with any number of non-modal windows with convenience functions too. Create and configure windows in the same manner as you would prior to calling XuiGetReply() . But add a "SetCallback" line like the second line below :

XuiCreateWindow (@g, @"XuiColor", 100, 256, 0, 0, 0, "")
XuiSendStringMessage ( g, @"SetCallback", g, &XuiQueueCallbacks() , -1, -1, $win, -1)
XuiSendStringMessage ( g, @"SetGridName", 0, 0, 0, 0, 0, @"Color")
XuiSendStringMessage ( g, @"DisplayWindow", 0, 0, 0, 0, 0, 0)
XuiSendStringMessage ( g, @"HideWindow", 0, 0, 0, 0, 0, 0)

$win is an integer you choose to distinguish this window from others. If your program has only one window, this argument can be -1 or 0 .

Your programs have to explicitly display and hide non-modal windows. Your programs can send "DisplayWindow" and "HideWindow" messages at any time to display and hide windows.

non-modal message loop
Programs wait for callback messages from non-modal windows in a message loop like the one below. Most callback messages are initiated by user actions like mouse button clicks and Enter keystrokes.

DO
XgrProcessMessages (1)
DO WHILE XuiGetNextCallback (@grid, @message$, @v0, @v1, @v2, @v3, @kid, @r1$)
GOSUB Callback
LOOP
LOOP
RETURN
'
SUB Callback
win = kid >> 16 ' win = which window is this callback from
kid = kid AND 0xFF ' kid = which kid in the window is this callback from
GOSUB @sub[win] ' handler for this window. or @func[] or SELECT CASE win
END SUB

The message loop is actually two loops - the outer loop processes messages one by one, and the inner loop processes all callback messages received by XuiQueueCallbacks() from processing each one.

XgrProcessMessages(1) waits for a message to become available, processes it, then returns. Processing a message usually does not generate a callback message. When it does, it usually generates a single callback message, though it will occasionally generate two or three.

XuiGetNextCallback() checks to see if XuiQueueCallbacks() received any callback messages as a result of processing the message. If no callback message was received, XuiGetNextCallback() returns a zero which terminates the inner loop and drops back into the outer message processing loop. If XuiQueueCallbacks() has one or more callback messages waiting, XuiGetNextCallback() transfers the callback arguments to its own arguments and returns a non-zero value. This drops the code into GOSUB Callback which calls a subroutine that processes the callback message.

XuiGetNextCallback()
XuiGetNextCallback() returns the same callback arguments as conventional programs, except the upper 16-bits of kid contains the window identifier set by the "SetCallback" message, and r1$ contains the GridName property of the grid that initiated the callback. Your program can respond to specific grids in a most convenient and readable manner if it sends "SetGridName" to every grid it creates, including kid grids. Most programs respond to callbacks from each window separately.